package com.lhl.jwt.security.filter;

import cn.hutool.core.util.StrUtil;
import com.lhl.jwt.excepiton.JwtException;
import com.lhl.jwt.security.token.MiniAppAuthenticationToken;
import com.lhl.jwt.security.vo.MiniAppVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @className: com.lhl.jwt.security.filter.MiniAppAuthenticationProcessingFilter
 * @description: 小程序登入校验,用于用户认证的filter，但是真正的认证逻辑会委托给MiniAppAuthenticationProvider
 * @author: king
 * @date: 2020-12-21 14:52
 **/
@Slf4j
public class MiniAppAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private String appId;

    private String appSrcret;

    private RestTemplate restTemplate;

    private String wxAuthUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
    public MiniAppAuthenticationFilter(){
        super(new AntPathRequestMatcher("/miniApp/doLogin", "POST"));
    }

    public MiniAppAuthenticationFilter(String appId,
                                       String appSrcret,
                                       RestTemplate restTemplate) {
        super(new AntPathRequestMatcher("/miniApp/doLogin", "POST"));
        this.appId = appId;
        this.appSrcret = appSrcret;
        this.restTemplate = restTemplate;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        String code = request.getParameter("code");
        Assert.notNull(code, "code is null");
        String rawData = request.getParameter("rawData");
        Assert.notNull(rawData, "rawData is null");
        String signature = request.getParameter("signature");
        Assert.notNull(signature, "signature is null");
        String url = String.format(wxAuthUrl, appId, appSrcret, code);
        log.debug("wx auth url: [{}]", url);
        MiniAppVO miniAppVO = restTemplate.getForObject(url, MiniAppVO.class);
        if(miniAppVO.getErrcode() != null && !miniAppVO.getErrcode().equals(0)){
            log.error("wx auth failed, errCode is [{}], errMsg is [{}]", miniAppVO.getErrcode(), miniAppVO.getErrmsg());
            throw new JwtException(StrUtil.format("wx auth failed, errCode is {}, errMsg is {}", miniAppVO.getErrcode(), miniAppVO.getErrmsg()));
        }
        log.info("wx login result: [{}]", miniAppVO);
        return this.getAuthenticationManager().authenticate(new MiniAppAuthenticationToken(miniAppVO.getOpenid(), miniAppVO.getSession_key(), rawData, signature));
    }
}
